/*
 * Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
 *
 * This work is free. You can redistribute it and/or modify it under the
 * terms of the Do What The Fuck You Want To Public License, Version 2,
 * as published by Sam Hocevar. See the COPYING file for more details.
 */

#include "Window.h"
#include "ui_Window.h"

#include <QDebug>
#include <QSimpleUpdater.h>

#include <QMessageBox>
#include <QProcess>
#include <windows.h>//winApi函数
#include <winbase.h>//winApi函数

#include "QtGui/private/qzipreader_p.h"
#include <QFileInfo>
#include <QFile>
#include <QDir>
//==============================================================================
// Define the URL of the Update Definitions file
//==============================================================================

//==============================================================================
// Window::Window
//==============================================================================

Window::Window(QWidget *parent)
    : QMainWindow(parent)
{
    m_ui = new Ui::Window;
    m_ui->setupUi(this);

    setWindowTitle(qApp->applicationName());

    /* QSimpleUpdater is single-instance */
    m_updater = QSimpleUpdater::getInstance();

    /* Check for updates when the "Check For Updates" button is clicked */
    connect(m_updater, SIGNAL(checkingFinished(QString)), this, SLOT(updateChangelog(QString)));
    connect(m_updater, SIGNAL(appcastDownloaded(QString, QByteArray)), this, SLOT(displayAppcast(QString, QByteArray)));

    connect(m_updater, SIGNAL(downloadFinished(QString, QString)), this, SLOT(getDownloadFinined(QString, QString)));

    /* React to button clicks */
    connect(m_ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(m_ui->checkButton, SIGNAL(clicked()), this, SLOT(get_updeDownload()));

    /* Resize the dialog to fit */
    checkForUpdates();
}

//==============================================================================
// Window::~Window
//==============================================================================

Window::~Window()
{
    delete m_ui;
}

//==============================================================================
// Window::checkForUpdates
//==============================================================================


//==============================================================================
// Window::checkForUpdates
//==============================================================================

void Window::checkForUpdates()
{
    DEFS_URL = qApp->arguments().at(3);
    if(DEFS_URL == "")
    {
        QMessageBox::critical(this, "error", "url is empty");
        return;
    }
    /* Apply the settings */
    m_updater->setNotifyOnFinish(DEFS_URL, false);
    m_updater->setNotifyOnUpdate(DEFS_URL, false);
    /* Check for updates */
    m_updater->checkForUpdates(DEFS_URL);
}

//==============================================================================
// Window::updateChangelog
//==============================================================================

void Window::updateChangelog(const QString &url)
{
    QString version = qApp->arguments().at(1);
    if(version == m_updater->getLatestVersion(DEFS_URL))
    {
        qApp->quit();
    }
    else {
        this->show();
    }
    if (url == DEFS_URL)
        m_ui->changelogText->setText(m_updater->getChangelog(url));
}

//==============================================================================
// Window::displayAppcast
//==============================================================================

void Window::displayAppcast(const QString &url, const QByteArray &reply)
{
    if (url == DEFS_URL)
    {
        QString text = "This is the downloaded appcast: <p><pre>" + QString::fromUtf8(reply)
                + "</pre></p><p> If you need to store more information on the "
                  "appcast (or use another format), just use the "
                  "<b>QSimpleUpdater::setCustomAppcast()</b> function. "
                  "It allows your application to interpret the appcast "
                  "using your code and not QSU's code.</p>";

        m_ui->changelogText->setText(text);
    }
}


void Window::getDownloadFinined(const QString &url, const QString &filepath)
{
    Q_UNUSED(url);
    Q_UNUSED(filepath);

    QString pid = qApp->arguments().at(2);
    if(pid != "")
        killProcess(pid);    // kill主程序

//    QProcess cmd(this);
//    QString script = "unpack/unpack.bat";
//    cmd.startDetached(script);
//    cmd.waitForStarted();
//    cmd.waitForFinished();
//    qApp->quit();

    bool flag = decompression_file_run("release.zip", "./");
    flag = copyDir("release", "./", true);
    flag = delFileOrDir("release");
    flag = delFileOrDir("release.zip");
//    QMessageBox::information(this, "info", QString().number(flag));
    qApp->quit();
}

void Window::get_updeDownload()
{
    m_updater->setNotifyOnFinish(DEFS_URL, true);
    m_updater->setNotifyOnUpdate(DEFS_URL, true);
    m_updater->setDownloaderEnabled(DEFS_URL, true);
    m_updater->setUseCustomInstallProcedures(DEFS_URL, true);
    m_updater->checkForUpdates(DEFS_URL);
}

void Window::killProcess(QString pid)
{
#ifdef WIN32//Windows系统
    /**
     * 强制杀死当前进程，同时推出所有子线程
     * TASKKILL 参数解释：
     * /T : 杀死当前进程启动和其启动的所有子线程
     * /F: 强制杀死进程
     * */
    QString cmd = QString("taskkill /f /pid ") + pid;

    //@ 可以，无dos黑窗口
    WinExec(cmd.toLocal8Bit().data(), SW_HIDE);//SW_HIDE：控制运行cmd时，不弹出cmd运行窗口
#endif
}

bool Window::decompression_file_run(QString srcPath, QString destPath)
{
    if(srcPath == nullptr || destPath == nullptr)
        return false;

    QFileInfo srcFileInfo(srcPath);
    if(!srcFileInfo.isFile() || srcFileInfo.suffix() != "zip")
        return false;
    QZipReader *zipReader = new QZipReader(srcPath);
    bool res = zipReader->extractAll(destPath);
    zipReader->close();
    delete zipReader;
    return res;
}

// 复制文件夹
bool Window::copyDir(const QString &sSrcDir, const QString &sDestDir, const bool &bCover)
{
    // 是否传入了空的路径||源文件夹是否存在
    if (sSrcDir.isEmpty() || sDestDir.isEmpty() || !QDir().exists(sSrcDir))
        return false;

    QDir sourceDir(sSrcDir);
    QDir destDir(sDestDir);

//    // 如果目标目录不存在，则进行创建
//    if(!destDir.exists()) {
//        if(!(createDir(destDir.absolutePath())))
//            return false;
//    }

    QFileInfoList fileInfoList = sourceDir.entryInfoList();
    foreach(QFileInfo fileInfo, fileInfoList) {
        if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        // 当为目录时，递归的进行copy
        if(fileInfo.isDir()) {
            // 若目标目录不存在待拷贝文件夹，则创建
            if(!destDir.exists(fileInfo.fileName()))
                destDir.mkdir(fileInfo.fileName());
            if(!copyDir(fileInfo.filePath(),
                destDir.filePath(fileInfo.fileName()),
                bCover))
                return false;
        }
        else { // 当允许覆盖操作时，将旧文件进行删除操作
            if(bCover && destDir.exists(fileInfo.fileName())){
                destDir.remove(fileInfo.fileName());
             }

            // 进行文件copy
//            if(!QFile::copy(fileInfo.filePath(),
//                destDir.filePath(fileInfo.fileName()))){
//                    return false
//            }
            // 进行文件copy,文件占用忽略报错
            QFile::copy(fileInfo.filePath(), destDir.filePath(fileInfo.fileName()));
        }
    }

    return true;
}

// 删除文件或文件夹
bool Window::delFileOrDir(const QString &sPath)
{
    //是否传入了空的路径||路径是否存在
    if (sPath.isEmpty() || !QDir().exists(sPath))
        return false;

    QFileInfo FileInfo(sPath);
    if (FileInfo.isFile()) // 如果是文件
        return QFile::remove(sPath);
    else if (FileInfo.isDir()) // 如果是文件夹
    {
        QDir qDir(sPath);
        return qDir.removeRecursively();
    }

    return true;
}

